﻿namespace Yaaf.WP7.NativeAccess.ComWrapper.HTC.COM_NativeAccess
{
    using System.Runtime.InteropServices;

    using Microsoft.Phone.InteropServices;

    using System;

    using Yaaf.WP7.NativeAccess.Helper;
    using Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess;

    internal static class FileSystem
    {
        private static global::Yaaf.WP7.NativeAccess.ComWrapper.HTC.COM_NativeAccess.INativeAccess nativeAccess;

        static FileSystem()
        {
            Devices.Initialize();
            FileViewer.Initialize();
            if (ComBridge.RegisterComDll("COM_NativeAccess.dll", new Guid("787049D8-AF63-4B2D-B21C-4EBC7C8C8787")) != 0)
            {
                throw new RegisterComException("Register COM Dll Fail.");
            }
            nativeAccess = new NativeAccess() as global::Yaaf.WP7.NativeAccess.ComWrapper.HTC.COM_NativeAccess.INativeAccess;
        }

        internal static int NextElement(IntPtr handle, out FileSystemEntryStructure A_1)
        {
            return nativeAccess.NextElement(handle, out A_1);
        }

        internal static int CloseEnumerator(IntPtr A_0)
        {
            return nativeAccess.CloseEnumerator(A_0);
        }

        internal static int StartEnumerateDirectory(string A_0, out FileSystemEntryStructure A_1, out IntPtr A_2)
        {
            return nativeAccess.StartEnumerateDirectory(A_0, out A_1, out A_2);
        }
        
        public static int CloseFile(IntPtr hFile)
        {
            return nativeAccess.CloseFile(hFile);
        }

        public static int CopyFile(string sourceFilename, string destinationFilename, bool failIfExists)
        {
            int num = nativeAccess.CopyFile(sourceFilename, destinationFilename, failIfExists);
            if ((num == 0) && (Microsoft.Phone.InteropServices.Marshal.GetLastWin32Error() == -2147483643))
            {
                throw new UnauthorizedAccessException("Access denied");
            }
            return num;
        }

        internal static int Seek(IntPtr file, long offset, global::Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess.SeekOriginInternal origin)
        {
            global::Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess.FileSizeStruct fileSizeStruct = new global::Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess.FileSizeStruct {
                size = offset
            };
            int num = FileSystem.nativeAccess.Seek(file, fileSizeStruct.upper, ref fileSizeStruct.lower, (int) origin);
            if (num == -1)
            {
                throw new Exception("Invalid seek");
            }
            return num;
        }

        public static long GetFileSize(IntPtr hFile)
        {
            global::Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess.FileSizeStruct fileSizeStruct;
            fileSizeStruct = new global::Yaaf.WP7.NativeAccess.IO.Internals.HTC.COM_NativeAccess.FileSizeStruct {
                upper = FileSystem.nativeAccess.GetFileSize(hFile, out fileSizeStruct.lower)
            };
            if (fileSizeStruct.upper == -1)
            {
                throw new Exception("Invalid file size");
            }
            return fileSizeStruct.size;
        }

        public static DateTime GetFileTime(string fileName)
        {
            long num;
            long num2;
            long num3;
            Console.WriteLine(nativeAccess.GetFileTime(fileName, out num, out num3, out num2));
            if (nativeAccess.GetFileTime(fileName, out num, out num3, out num2) == 0)
            {
                return DateTime.FromFileTime(num2);
            }
            return DateTime.MinValue;
        }

        public static int OpenFile(string lpFilename, FileAccess dwDesiredAccess, FileShare dwShareMode, CreationDisposition dwCreationDisposition, FileAttributes dwFlagsAndAttributes, out IntPtr hFile)
        {
            return nativeAccess.OpenFile(lpFilename, (int) dwDesiredAccess, (int) dwShareMode, (int) dwCreationDisposition, (int) dwFlagsAndAttributes, out hFile);
        }

        public static int ReadFile(IntPtr hfile, byte[] buffer, int nNumberOfBytesToRead, int offset, out int lpNumberOfBytesRead)
        {
            Microsoft.Phone.InteropServices.GCHandle handle = Microsoft.Phone.InteropServices.GCHandle.Alloc(buffer, GCHandleType.Pinned);
            int num = nativeAccess.ReadFile(hfile, new IntPtr(handle.AddrOfPinnedObject().ToInt32() + offset), nNumberOfBytesToRead, out lpNumberOfBytesRead);
            handle.Free();
            if ((num == 0) && (Microsoft.Phone.InteropServices.Marshal.GetLastWin32Error() == -2147483643))
            {
                throw new UnauthorizedAccessException("Access denied");
            }
            return num;
        }
    }
}

